using ERP.Common.Results;
using ERP.Team.ProductionSystem;
using ERP.ERPSystem.ProductionSystem.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;

namespace ERP.ERPSystem.ProductionSystem
{
    /// <summary>
    /// 物料需求服务实现
    /// </summary>
    public class MaterialRequirementServices : ApplicationService, IMaterialRequirementServices
    {
        private readonly IRepository<MaterialRequirementModel, int> _materialRequirementRepository;
        private readonly IRepository<CustomerOrderModel, int> _customerOrderRepository;
        private readonly IRepository<MaterialproductModel, int> _materialproductRepository;

        public MaterialRequirementServices(
            IRepository<MaterialRequirementModel, int> materialRequirementRepository,
            IRepository<CustomerOrderModel, int> customerOrderRepository,
            IRepository<MaterialproductModel, int> materialproductRepository)
        {
            _materialRequirementRepository = materialRequirementRepository;
            _customerOrderRepository = customerOrderRepository;
            _materialproductRepository = materialproductRepository;
        }

        /// <summary>
        /// 根据客户订单ID获取物料需求列表
        /// </summary>
        /// <param name="customerOrderId">客户订单ID</param>
        /// <returns>物料需求列表</returns>
        public async Task<List<MaterialRequirementModel>> GetMaterialRequirementsByOrderId(int customerOrderId)
        {
            try
            {
                var requirements = await _materialRequirementRepository.GetListAsync(
                    x => x.CustomerOrderId == customerOrderId && !x.IsDeleted);
                
                return requirements.OrderBy(x => x.SortOrder)
                                 .ThenBy(x => x.Level)
                                 .ThenBy(x => x.Id)
                                 .ToList();
            }
            catch (Exception ex)
            {
                throw new Exception($"获取物料需求列表失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 分页查询物料需求列表
        /// </summary>
        /// <param name="queryDto">查询条件</param>
        /// <returns>分页物料需求列表</returns>
        public async Task<APIPaging<MaterialRequirementModel>> GetMaterialRequirementList(MaterialRequirementQueryDto queryDto)
        {
            try
            {
                var pageList = new APIPaging<MaterialRequirementModel>();
                var query = await _materialRequirementRepository.GetQueryableAsync();

                // 条件筛选
                query = query.Where(x => !x.IsDeleted);

                query = query.WhereIf(queryDto.CustomerOrderId.HasValue,
                    x => x.CustomerOrderId == queryDto.CustomerOrderId.Value);

                query = query.WhereIf(!string.IsNullOrEmpty(queryDto.MaterialCode),
                    x => x.MaterialCode.Contains(queryDto.MaterialCode));

                query = query.WhereIf(!string.IsNullOrEmpty(queryDto.MaterialName),
                    x => x.MaterialName.Contains(queryDto.MaterialName));

                query = query.WhereIf(queryDto.IsLevelTitle.HasValue,
                    x => x.IsLevelTitle == queryDto.IsLevelTitle.Value);

                // 计算总数
                pageList.PageCount = query.Count();

                // 分页和排序
                pageList.ListDate = query
                    .OrderBy(x => x.CustomerOrderId)
                    .ThenBy(x => x.SortOrder)
                    .ThenBy(x => x.Level)
                    .ThenBy(x => x.Id)
                    .Skip((queryDto.Page - 1) * queryDto.Limit)
                    .Take(queryDto.Limit)
                    .ToList();

                // 计算总页数
                pageList.PageIndex = Convert.ToInt32(Math.Ceiling(pageList.PageCount * 1.0 / queryDto.Limit));

                return pageList;
            }
            catch (Exception ex)
            {
                throw new Exception($"查询物料需求列表失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 根据ID获取物料需求详情
        /// </summary>
        /// <param name="id">需求ID</param>
        /// <returns>物料需求详情</returns>
        public async Task<MaterialRequirementModel> GetMaterialRequirementById(int id)
        {
            try
            {
                var requirement = await _materialRequirementRepository.FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted);
                if (requirement == null)
                {
                    throw new ArgumentException($"物料需求ID {id} 不存在");
                }
                return requirement;
            }
            catch (Exception ex)
            {
                throw new Exception($"获取物料需求详情失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 添加物料需求
        /// </summary>
        /// <param name="materialRequirementDto">物料需求信息</param>
        /// <returns>需求ID</returns>
        public async Task<int> AddMaterialRequirement(MaterialRequirementDto materialRequirementDto)
        {
            try
            {
                // 验证客户订单是否存在
                var order = await _customerOrderRepository.FirstOrDefaultAsync(x => x.Id == materialRequirementDto.CustomerOrderId);
                if (order == null)
                {
                    throw new ArgumentException($"客户订单ID {materialRequirementDto.CustomerOrderId} 不存在");
                }

                // 创建物料需求实体
                var materialRequirement = new MaterialRequirementModel
                {
                    CustomerOrderId = materialRequirementDto.CustomerOrderId,
                    ParentId = materialRequirementDto.ParentId,
                    Level = materialRequirementDto.Level,
                    IsLevelTitle = materialRequirementDto.IsLevelTitle,
                    LevelTitle = materialRequirementDto.LevelTitle ?? "",
                    MaterialCode = materialRequirementDto.MaterialCode ?? "",
                    MaterialName = materialRequirementDto.MaterialName ?? "",
                    Specifications = materialRequirementDto.Specifications ?? "",
                    RequiredQuantity = materialRequirementDto.RequiredQuantity,
                    InventoryQuantity = materialRequirementDto.InventoryQuantity,
                    Unit = materialRequirementDto.Unit ?? "",
                    Remark = materialRequirementDto.Remark ?? "",
                    SortOrder = materialRequirementDto.SortOrder,
                    CreateUser = materialRequirementDto.CreateUser ?? "",
                    CreateTime = DateTime.Now
                };

                // 插入到数据库
                var result = await _materialRequirementRepository.InsertAsync(materialRequirement, autoSave: true);
                return result.Id;
            }
            catch (Exception ex)
            {
                throw new Exception($"添加物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 更新物料需求
        /// </summary>
        /// <param name="materialRequirementDto">物料需求信息</param>
        /// <returns>更新结果</returns>
        public async Task<bool> UpdateMaterialRequirement(MaterialRequirementDto materialRequirementDto)
        {
            try
            {
                // 验证物料需求是否存在
                var existingRequirement = await _materialRequirementRepository.FirstOrDefaultAsync(
                    x => x.Id == materialRequirementDto.Id && !x.IsDeleted);
                if (existingRequirement == null)
                {
                    throw new ArgumentException($"物料需求ID {materialRequirementDto.Id} 不存在");
                }

                // 更新物料需求信息
                existingRequirement.ParentId = materialRequirementDto.ParentId;
                existingRequirement.Level = materialRequirementDto.Level;
                existingRequirement.IsLevelTitle = materialRequirementDto.IsLevelTitle;
                existingRequirement.LevelTitle = materialRequirementDto.LevelTitle ?? "";
                existingRequirement.MaterialCode = materialRequirementDto.MaterialCode ?? "";
                existingRequirement.MaterialName = materialRequirementDto.MaterialName ?? "";
                existingRequirement.Specifications = materialRequirementDto.Specifications ?? "";
                existingRequirement.RequiredQuantity = materialRequirementDto.RequiredQuantity;
                existingRequirement.InventoryQuantity = materialRequirementDto.InventoryQuantity;
                existingRequirement.Unit = materialRequirementDto.Unit ?? "";
                existingRequirement.Remark = materialRequirementDto.Remark ?? "";
                existingRequirement.SortOrder = materialRequirementDto.SortOrder;
                existingRequirement.UpdateUser = materialRequirementDto.UpdateUser ?? "";
                existingRequirement.UpdateTime = DateTime.Now;

                // 保存更改
                await _materialRequirementRepository.UpdateAsync(existingRequirement, autoSave: true);
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"更新物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 批量保存物料需求（删除原有数据，重新保存）
        /// </summary>
        /// <param name="batchSaveDto">批量保存DTO</param>
        /// <returns>保存结果</returns>
        public async Task<bool> BatchSaveMaterialRequirements(BatchSaveMaterialRequirementDto batchSaveDto)
        {
            try
            {
                // 验证客户订单是否存在
                var order = await _customerOrderRepository.FirstOrDefaultAsync(x => x.Id == batchSaveDto.CustomerOrderId);
                if (order == null)
                {
                    throw new ArgumentException($"客户订单ID {batchSaveDto.CustomerOrderId} 不存在");
                }

                // 删除原有的物料需求
                var existingRequirements = await _materialRequirementRepository.GetListAsync(
                    x => x.CustomerOrderId == batchSaveDto.CustomerOrderId);
                if (existingRequirements.Any())
                {
                    await _materialRequirementRepository.DeleteManyAsync(existingRequirements, autoSave: false);
                }

                // 批量插入新的物料需求
                if (batchSaveDto.MaterialRequirements.Any())
                {
                    var newRequirements = batchSaveDto.MaterialRequirements.Select(dto => new MaterialRequirementModel
                    {
                        CustomerOrderId = batchSaveDto.CustomerOrderId,
                        ParentId = dto.ParentId,
                        Level = dto.Level,
                        IsLevelTitle = dto.IsLevelTitle,
                        LevelTitle = dto.LevelTitle ?? "",
                        MaterialCode = dto.MaterialCode ?? "",
                        MaterialName = dto.MaterialName ?? "",
                        Specifications = dto.Specifications ?? "",
                        RequiredQuantity = dto.RequiredQuantity,
                        InventoryQuantity = dto.InventoryQuantity,
                        Unit = dto.Unit ?? "",
                        Remark = dto.Remark ?? "",
                        SortOrder = dto.SortOrder,
                        CreateUser = dto.CreateUser ?? "",
                        CreateTime = DateTime.Now
                    }).ToList();

                    await _materialRequirementRepository.InsertManyAsync(newRequirements, autoSave: true);
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"批量保存物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 删除物料需求
        /// </summary>
        /// <param name="id">需求ID</param>
        /// <returns>删除结果</returns>
        public async Task<bool> DeleteMaterialRequirement(int id)
        {
            try
            {
                var requirement = await _materialRequirementRepository.FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted);
                if (requirement == null)
                {
                    throw new ArgumentException($"物料需求ID {id} 不存在");
                }

                // 软删除
                requirement.IsDeleted = true;
                requirement.UpdateTime = DateTime.Now;
                await _materialRequirementRepository.UpdateAsync(requirement, autoSave: true);
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"删除物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 批量删除物料需求
        /// </summary>
        /// <param name="ids">需求ID数组</param>
        /// <returns>删除结果</returns>
        public async Task<bool> DeleteMaterialRequirements(int[] ids)
        {
            try
            {
                if (ids == null || ids.Length == 0)
                {
                    throw new ArgumentException("删除的物料需求ID不能为空");
                }

                var requirements = await _materialRequirementRepository.GetListAsync(x => ids.Contains(x.Id) && !x.IsDeleted);
                if (requirements.Count != ids.Length)
                {
                    var existingIds = requirements.Select(x => x.Id).ToArray();
                    var missingIds = ids.Except(existingIds).ToArray();
                    throw new ArgumentException($"以下物料需求ID不存在: {string.Join(", ", missingIds)}");
                }

                // 批量软删除
                foreach (var requirement in requirements)
                {
                    requirement.IsDeleted = true;
                    requirement.UpdateTime = DateTime.Now;
                }

                await _materialRequirementRepository.UpdateManyAsync(requirements, autoSave: true);
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"批量删除物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 根据客户订单ID删除所有相关物料需求
        /// </summary>
        /// <param name="customerOrderId">客户订单ID</param>
        /// <returns>删除结果</returns>
        public async Task<bool> DeleteMaterialRequirementsByOrderId(int customerOrderId)
        {
            try
            {
                var requirements = await _materialRequirementRepository.GetListAsync(x => x.CustomerOrderId == customerOrderId && !x.IsDeleted);
                if (requirements.Any())
                {
                    foreach (var requirement in requirements)
                    {
                        requirement.IsDeleted = true;
                        requirement.UpdateTime = DateTime.Now;
                    }
                    await _materialRequirementRepository.UpdateManyAsync(requirements, autoSave: true);
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"删除订单相关物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 复制物料需求到另一个订单
        /// </summary>
        /// <param name="sourceOrderId">源订单ID</param>
        /// <param name="targetOrderId">目标订单ID</param>
        /// <returns>复制结果</returns>
        public async Task<bool> CopyMaterialRequirements(int sourceOrderId, int targetOrderId)
        {
            try
            {
                // 验证源订单和目标订单是否存在
                var sourceOrder = await _customerOrderRepository.FirstOrDefaultAsync(x => x.Id == sourceOrderId);
                var targetOrder = await _customerOrderRepository.FirstOrDefaultAsync(x => x.Id == targetOrderId);
                
                if (sourceOrder == null)
                {
                    throw new ArgumentException($"源订单ID {sourceOrderId} 不存在");
                }
                if (targetOrder == null)
                {
                    throw new ArgumentException($"目标订单ID {targetOrderId} 不存在");
                }

                // 获取源订单的物料需求
                var sourceRequirements = await _materialRequirementRepository.GetListAsync(
                    x => x.CustomerOrderId == sourceOrderId && !x.IsDeleted);

                if (sourceRequirements.Any())
                {
                    // 创建目标订单的物料需求
                    var targetRequirements = sourceRequirements.Select(source => new MaterialRequirementModel
                    {
                        CustomerOrderId = targetOrderId,
                        ParentId = source.ParentId,
                        Level = source.Level,
                        IsLevelTitle = source.IsLevelTitle,
                        LevelTitle = source.LevelTitle,
                        MaterialCode = source.MaterialCode,
                        MaterialName = source.MaterialName,
                        Specifications = source.Specifications,
                        RequiredQuantity = source.RequiredQuantity,
                        InventoryQuantity = source.InventoryQuantity,
                        Unit = source.Unit,
                        Remark = source.Remark,
                        SortOrder = source.SortOrder,
                        CreateTime = DateTime.Now
                    }).ToList();

                    await _materialRequirementRepository.InsertManyAsync(targetRequirements, autoSave: true);
                }

                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"复制物料需求失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取物料需求的树形结构数据
        /// </summary>
        /// <param name="customerOrderId">客户订单ID</param>
        /// <returns>树形结构的物料需求列表</returns>
        public async Task<List<MaterialRequirementDto>> GetMaterialRequirementTree(int customerOrderId)
        {
            try
            {
                var requirements = await GetMaterialRequirementsByOrderId(customerOrderId);
                
                // 将实体转换为DTO
                var requirementDtos = requirements.Select(x => new MaterialRequirementDto
                {
                    Id = x.Id,
                    CustomerOrderId = x.CustomerOrderId,
                    ParentId = x.ParentId,
                    Level = x.Level,
                    IsLevelTitle = x.IsLevelTitle,
                    LevelTitle = x.LevelTitle,
                    MaterialCode = x.MaterialCode,
                    MaterialName = x.MaterialName,
                    Specifications = x.Specifications,
                    RequiredQuantity = x.RequiredQuantity,
                    InventoryQuantity = x.InventoryQuantity,
                    Unit = x.Unit,
                    Remark = x.Remark,
                    SortOrder = x.SortOrder,
                    CreateTime = x.CreateTime,
                    CreateUser = x.CreateUser,
                    UpdateTime = x.UpdateTime,
                    UpdateUser = x.UpdateUser
                }).ToList();

                return requirementDtos;
            }
            catch (Exception ex)
            {
                throw new Exception($"获取物料需求树形结构失败: {ex.Message}", ex);
            }
        }
    }
} 